﻿using StbImageSharp;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using static StbImageSharp.StbImage;
using static System.Net.Mime.MediaTypeNames;

namespace ttbit.core
{
    public class TextureData_Ex
    {
        public int width;
        public int height;
        public Color[] paldata;
        public int[] framedelay;
        public byte[][] data;
    }
    public static class CoreLoadTool
    {

        public static byte[] LoadTextureData_RGBA(byte[] data, out int width, out int height)
        {

            ImageResult image = ImageResult.FromMemory(data, ColorComponents.RedGreenBlueAlpha);
            if (image.Comp != ColorComponents.RedGreenBlueAlpha)
                throw new Exception("only support rgba here.");
            width = image.Width;
            height = image.Height;
            return image.Data;
        }
        public static byte[] LoadTextureData_RGBA(System.IO.Stream stream, out int width, out int height)
        {
            
            ImageResult image = ImageResult.FromStream(stream, ColorComponents.RedGreenBlueAlpha);
            if (image.Comp != ColorComponents.RedGreenBlueAlpha)
                throw new Exception("only support rgba here.");
            width = image.Width;
            height = image.Height;
            return image.Data;
        }

        public static void GetBorder(byte[] data, int w, int h, out int x, out int y, out int x2, out int y2)
        {
            x = int.MaxValue;
            x2 = int.MinValue;
            y = int.MaxValue;
            y2 = int.MinValue;
            for (var _y = 0; _y < h; _y++)
            {
                for (var _x = 0; _x < w; _x++)
                {
                    var seekr = (_y * w + _x) * 4 + 3;
                    var alpha = (int)(((float)data[seekr] / 255.0) * 7);//小于1/7 视为透明
                    if (alpha > 0)
                    {
                        if (x > _x) x = _x;
                        if (x2 < _x) x2 = _x;
                        if (y > _y) y = _y;
                        if (y2 < _y) y2 = _y;
                    }
                }
            }
        }

        //public static TextureData_Ex LoadTextureData_RGBA_EX(System.IO.Stream stream)
        //{
        //    unsafe
        //    {
        //        var context = new StbImage.stbi__context(stream);
        //        if (StbImage.stbi__gif_test(context) == 1)
        //        {

        //            stbi__gif header = new stbi__gif();
        //            int* delays = null;
        //            int x, y, z, comp;
        //            void* result = StbImage.stbi__load_gif_main_ex(context, header, &delays, &x, &y, &z, &comp, (int)ColorComponents.RedGreenBlueAlpha) ;
        //            TextureData_Ex data = new TextureData_Ex();
        //            data.width = x;
        //            data.height = y;
        //            data.framedelay = new int[z];
        //            for (var i = 0; i < z; i++)
        //            {
        //                data.framedelay[i] = delays[i];
        //            }

        //            int compsize = 4;
        //            data.data = new byte[z][];
        //            for (var i = 0; i < z; i++)
        //            {
        //                data.data[i] = new byte[x * y * compsize];
        //                int len = data.data[i].Length;
        //                Marshal.Copy(new IntPtr((byte*)result+len*i), data.data[i], 0,len);
        //            }

        //            data.paldata = new Color[header.color_table.Length];
        //            for (var i = 0; i < header.color_table.Length; i++)
        //            {

        //                var r = header.color_table[i][2];
        //                var g = header.color_table[i][1];
        //                var b = header.color_table[i][0];
        //                var a = header.color_table[i][3];
        //                data.paldata[i] = Color.FromArgb(a, r, g, b);
        //            }

        //            return data;
        //        }
        //        else
        //        {

        //            int x, y, comp;



        //            byte* result = StbImage.stbi__load_and_postprocess_8bit(context, &x, &y, &comp, (int)ColorComponents.RedGreenBlueAlpha);
        //            TextureData_Ex data = new TextureData_Ex();
        //            data.width = x;
        //            data.height = y;
        //            data.framedelay = null;
        //            data.paldata = null;

        //            int compsize = 4;
        //            data.data = new byte[1][];
        //            data.data[0] = new byte[x * y * compsize];
        //            Marshal.Copy(new IntPtr(result), data.data[0], 0, data.data[0].Length);
        //            return data;
        //        }
        //    }
        //}


        public static Font LoadAscII(System.IO.Stream stream, byte size, TexturePacker texturePacker)
        {
            if (!texturePacker.Gray)
                throw new Exception("this function need graytexture.");
            Font font = new Font();
            font.size = size;
            font.texture = texturePacker.texture;

            byte[] data = new byte[stream.Length];
            stream.Read(data, 0, data.Length);

            //byte[] data = System.IO.File.ReadAllBytes(filename);

            byte halfsize = (byte)(size / 2);

            int bytewidth = halfsize / 8;
            if (halfsize % 8 > 0)
                bytewidth++;

            var cdata = new byte[size * halfsize];

            int datablocksize = size * bytewidth;

            for (var i = 32; i < 127; i++)//ascii key range
            {
                Array.Fill<byte>(cdata, 0);
                char c = (char)i;
                //TileInfo charinfo;
                int pixeloffsetX = int.MaxValue;
                int pixeloffsetY = int.MaxValue;
                //charinfo.pixeloffsetX = int.MaxValue;
                //charinfo.pixeloffsetY = int.MaxValue;
                int pixeloffsetXMax = int.MinValue;
                int pixeloffsetYMax = int.MinValue;

                bool empty = true;
                for (var y = 0; y < size; y++)
                {
                    var bit = data[(i - 32) * datablocksize + y];
                    if (bit == 0) continue;
                    for (var x = 0; x < 8; x++)
                    {
                        if (x >= halfsize) continue;
                        var mask = 1 << (7 - x);

                        if ((bit & mask) > 0)
                        {
                            cdata[y * halfsize + x] = 255;

                            if (pixeloffsetX > x)
                                pixeloffsetX = x;

                            if (pixeloffsetY > y)
                                pixeloffsetY = y;

                            if (pixeloffsetXMax < x) pixeloffsetXMax = x;
                            if (pixeloffsetYMax < y) pixeloffsetYMax = y;
                            empty = false;

                        }
                    }
                }
                if (empty)
                {
                    //空的还管他个屁
                    continue;
                }
                else
                {
                    int pixelSizeX = pixeloffsetXMax + 1 - pixeloffsetX;
                    int pixelSizeY = pixeloffsetYMax + 1 - pixeloffsetY;
                    var b = texturePacker.AddSprite(halfsize, size, cdata, true, true, out Sprite s);
                    // var s = texture.UpdateSprite_AutoCut(c.ToString(), halfsize, size, cdata);
                    if (b)
                        font.sprites[c] = s;
                    //var s = texture.UpdateSprite_Cut(c.ToString(), halfsize, size, cdata, (byte)pixeloffsetX, (byte)pixeloffsetY, pixelSizeX, pixelSizeY);
                }

                //bool b = texture.GetFreeTile(out charinfo.tileX, out charinfo.tileY);
                //if (!b) throw new Exception("TiledTexture is Full");
                //texture.UploadTile(charinfo.tileX, charinfo.tileY, cdata);
                //font.charTable[c.ToString()] = charinfo;
            }

            return font;
        }
    }
}
